﻿Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Reflection
Imports System.Workflow.ComponentModel

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class PropertySegmentPropertyInfo
        Inherits PropertyInfo
        ' Methods
        Friend Sub New(ByVal propertySegment As PropertySegment, ByVal realPropDesc As PropertyDescriptor)
            Me.realPropDesc = realPropDesc
            Me.propertySegment = propertySegment
        End Sub

        Friend Sub New(ByVal propertySegment As PropertySegment, ByVal realPropInfo As PropertyInfo)
            Me.realPropInfo = realPropInfo
            Me.propertySegment = propertySegment
        End Sub

        Public Overrides Function GetAccessors(ByVal nonPublic As Boolean) As MethodInfo()
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetAccessors(nonPublic)
            End If
            Return New MethodInfo(0  - 1) {}
        End Function

        Public Overrides Function GetCustomAttributes(ByVal inherit As Boolean) As Object()
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetCustomAttributes(inherit)
            End If
            Return New AttributeInfoAttribute(0  - 1) {}
        End Function

        Public Overrides Function GetCustomAttributes(ByVal attributeType As Type, ByVal inherit As Boolean) As Object()
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetCustomAttributes(attributeType, inherit)
            End If
            Return New AttributeInfoAttribute(0  - 1) {}
        End Function

        Public Overrides Function GetGetMethod(ByVal nonPublic As Boolean) As MethodInfo
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetGetMethod(nonPublic)
            End If
            Return Nothing
        End Function

        Public Overrides Function GetIndexParameters() As ParameterInfo()
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetIndexParameters
            End If
            Return New ParameterInfo(0  - 1) {}
        End Function

        Public Overrides Function GetSetMethod(ByVal nonPublic As Boolean) As MethodInfo
            If (Not Me.realPropInfo Is Nothing) Then
                Return Me.realPropInfo.GetSetMethod(nonPublic)
            End If
            Return Nothing
        End Function

        Public Overrides Function GetValue(ByVal obj As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal index As Object(), ByVal culture As CultureInfo) As Object
            Dim dependencyProperty As DependencyProperty = Nothing
            Dim activity As Activity = Nothing
            If (Not Me.propertySegment Is Nothing) Then
                activity = [TryCast](Me.propertySegment.Object,Activity)
            End If
            If (Not activity Is Nothing) Then
                Dim name As String = Me.Name
                Dim declaringType As Type = Me.DeclaringType
                If (Not String.IsNullOrEmpty(name) AndAlso (Not declaringType Is Nothing)) Then
                    dependencyProperty = DependencyProperty.FromName(name, declaringType)
                End If
            End If
            Dim binding As Object = Nothing
            Dim obj3 As Object = If((Me.propertySegment Is Nothing), obj, Me.propertySegment.Object)
            If ((Not dependencyProperty Is Nothing) AndAlso Not dependencyProperty.DefaultMetadata.IsMetaProperty) Then
                If activity.IsBindingSet(dependencyProperty) Then
                    binding = activity.GetBinding(dependencyProperty)
                ElseIf Not dependencyProperty.IsEvent Then
                    binding = activity.GetValue(dependencyProperty)
                Else
                    binding = activity.GetHandler(dependencyProperty)
                End If
            End If
            If (binding Is Nothing) Then
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.GetValue(obj3, invokeAttr, binder, index, culture)
                End If
                If (Not Me.realPropDesc Is Nothing) Then
                    binding = Me.realPropDesc.GetValue(obj3)
                End If
            End If
            Return binding
        End Function

        Public Overrides Function IsDefined(ByVal attributeType As Type, ByVal inherit As Boolean) As Boolean
            Return ((Not Me.realPropInfo Is Nothing) AndAlso Me.realPropInfo.IsDefined(attributeType, inherit))
        End Function

        Public Overrides Sub SetValue(ByVal obj As Object, ByVal value As Object, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal index As Object(), ByVal culture As CultureInfo)
            If (obj Is Nothing) Then
                Throw New ArgumentNullException("obj")
            End If
            Dim name As String = Me.Name
            Dim segment As PropertySegment = [TryCast](obj,PropertySegment)
            If (Not If((Not segment Is Nothing), [TryCast](segment.Object,Activity), [TryCast](obj,Activity)) Is Nothing) Then
                Dim declaringType As Type = Me.DeclaringType
                If (Not String.IsNullOrEmpty(name) AndAlso (Not declaringType Is Nothing)) Then
                    DependencyProperty.FromName(name, declaringType)
                End If
            End If
            Dim descriptor As PropertyDescriptor = Nothing
            Dim component As Object = Nothing
            If (segment Is Nothing) Then
                descriptor = TypeDescriptor.GetProperties(obj).Item(name)
                component = obj
            Else
                Dim properties As PropertyDescriptorCollection = Nothing
                Dim converter As TypeConverter = TypeDescriptor.GetConverter(segment.Object)
                If ((Not converter Is Nothing) AndAlso converter.GetPropertiesSupported) Then
                    Dim context As New DummyTypeDescriptorContext(segment.ServiceProvider, segment.Object, Me.realPropDesc)
                    properties = converter.GetProperties(context, segment.Object, New Attribute(0  - 1) {})
                Else
                    properties = TypeDescriptor.GetProperties(segment.Object)
                End If
                Dim descriptor2 As PropertyDescriptor
                For Each descriptor2 In properties
                    If (descriptor2.Name = name) Then
                        descriptor = descriptor2
                    ElseIf (Not descriptor2.Converter Is Nothing) Then
                        Dim context2 As New DummyTypeDescriptorContext(segment.ServiceProvider, segment.Object, descriptor2)
                        If ((Not descriptor2.GetValue(segment.Object) Is Nothing) AndAlso descriptor2.Converter.GetPropertiesSupported(context2)) Then
                            Dim descriptor3 As PropertyDescriptor
                            For Each descriptor3 In descriptor2.Converter.GetProperties(context2, descriptor2.GetValue(segment.Object), New Attribute(0  - 1) {})
                                If (descriptor3.Name = name) Then
                                    descriptor = descriptor3
                                End If
                            Next
                            [Continue] For
                        End If
                    End If
                Next
                component = segment.Object
            End If
            If ((Not descriptor Is Nothing) AndAlso (Not component Is Nothing)) Then
                descriptor.SetValue(component, value)
            End If
        End Sub


        ' Properties
        Public Overrides ReadOnly Property Attributes As PropertyAttributes
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.Attributes
                End If
                Return PropertyAttributes.None
            End Get
        End Property

        Public Overrides ReadOnly Property CanRead As Boolean
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.CanRead
                End If
                Return True
            End Get
        End Property

        Public Overrides ReadOnly Property CanWrite As Boolean
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.CanWrite
                End If
                Return ((Not Me.realPropDesc Is Nothing) AndAlso Not Me.realPropDesc.IsReadOnly)
            End Get
        End Property

        Public Overrides ReadOnly Property DeclaringType As Type
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.DeclaringType
                End If
                If (Not Me.realPropDesc Is Nothing) Then
                    Return Me.realPropDesc.ComponentType
                End If
                Return Nothing
            End Get
        End Property

        Public Overrides ReadOnly Property Name As String
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.Name
                End If
                If (Not Me.realPropDesc Is Nothing) Then
                    Return Me.realPropDesc.Name
                End If
                Return String.Empty
            End Get
        End Property

        Friend ReadOnly Property PropertySegment As PropertySegment
            Get
                Return Me.propertySegment
            End Get
        End Property

        Public Overrides ReadOnly Property PropertyType As Type
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.PropertyType
                End If
                If (Not Me.realPropDesc Is Nothing) Then
                    Return Me.realPropDesc.PropertyType
                End If
                Return Nothing
            End Get
        End Property

        Public Overrides ReadOnly Property ReflectedType As Type
            Get
                If (Not Me.realPropInfo Is Nothing) Then
                    Return Me.realPropInfo.ReflectedType
                End If
                Return Nothing
            End Get
        End Property


        ' Fields
        Private propertySegment As PropertySegment
        Private realPropDesc As PropertyDescriptor
        Private realPropInfo As PropertyInfo
    End Class
End Namespace

